/* Some code shared by the peak list pages that hooks the support provided by google_earth_plugin.inc.php
 * into the DOM elements on such pages. The following assumptions are made about the peak list page's DOM:
 *
 * map_show_hide_ID		  - An <a> to contain the show/hide control and link text that calls
 *							show_hide_google_earth() whenever it's clicked.
 * google_earth_area_ID   - A <div> to hide/show containing google_earth_ID and anything else you want
 * google_earth_ID		  - A <div class='google_earth'> containing just the Google Earth instance
 *
 * Optional:
 * map_show_hide_extra_ID - A <span> that will be removed the first time show_hide_google_earth() is called.
 *							This is useful for non-link text in the control's initial state.
 * click_peak_name_tip_ID - A <span> that will be replaced with text explaining what happens when you
 *							click a peak name (i.e., either going to the detail page or flying to the peak
 *							in Google Earth, depending on whether the Google Earth panel is open).
 *							Several such <span> elements may be included if they are given names of the
 *							form "click_peak_name_tip_1_ID", "click_peak_name_tip_2_ID", etc. We stop
 *							looping on the first of these that doesn't exist.
 * climbed_peak_UID_nnn   - A <td> for each peak summited by the climber, where "nnn" is the peak UID.
 *
 * For example, ca_14ers.php contains the following HTML:
 *
 *   <tr align="left">
 *    <td>
 *		<a id="map_show_hide_ID" class="data_list" href="#" onclick="show_hide_google_earth()"></a>
 *		<span id="map_show_hide_extra_ID">
 *			to display the California <?php echo($peak_list->get_peak_subset_name()); ?> on this page
 *		</span>
 *	</td>
 *  </tr>
 * 
 *  <tr align="left">
 *    <td>
 *    <div id="google_earth_area_ID" style="display: none;">
 *	  <p>The following interactive map displays the California <?php echo($peak_list->get_peak_subset_name()); ?>. Clicking a peak marker displays a window containing information about the summit. Double-clicking a peak marker &ldquo;flies&rdquo; to a location just above that summit.</p>
 *      <div id="google_earth_ID" class="google_earth"></div>
 *    </div>
 *      <p>or just <a class='data_list' href="./google_earth_kml.php?peak_subset_name=Fourteeners">download the list's KML file</a> to load into the separate <a href="http://earth.google.com/" target="_blank">Google Earth</a> application (also free).</p>
 *    </td>
 *  </tr>
 * 
 * NOTE: Don't forget to include lib/google_earth_plugin.inc.php, and then call
 *		 echo_google_earth_javascript($peak_list, $onLoad_handler); after building your peak list
 *		 and selecting a handler to pass in (show_it/hide_it/default_onLoad_handler - see below).
 */

/* Note: Our Google Earth instance needs global scope so that it will persist after we return
 * from show_hide_google_earth the first time.
 */
var google_earth_plugin = null;

/* Our google_earth_area_ID usually starts out hidden, and we don't even load the Google Earth APIs until
 * the user decides to show the Google Earth panel (calling show_hide_google_earth the first time).
 * Install one of the following onLoad handlers by passing an invocation statement as a string to
 * echo_google_earth_javascript. For example, ca_14ers.php has the following PHP code:
 *
 * 
 */
function show_it_onLoad_handler() {
	show_hide_google_earth();
}
function hide_it_onLoad_handler() {
	document.getElementById('map_show_hide_ID').innerHTML = SHOW_HIDE_HIDDEN_HTML;

	/* Toss any extra text currently displayed (used to help explain unloaded plugin, etc.)
	 */
	var show_hide_extra = document.getElementById("map_show_hide_extra_ID");
	if (show_hide_extra) {
		show_hide_extra.parentNode.removeChild(show_hide_extra);
	}
}
function default_onLoad_handler() {
	document.getElementById('map_show_hide_ID').innerHTML = SHOW_HIDE_INITIAL_HTML;
}

/* Show the <div> containing our map first so that the Google Earth APIs can use its
 * true dimensions to set up element sizes, etc. We delay actually (re)fetching/parsing our KML
 * until after google.load finishes loading all of the APIs and calls show_google_earth.
 */
function show_hide_google_earth() {
	var map_area = document.getElementById("google_earth_area_ID");
	var show_hide = document.getElementById("map_show_hide_ID");
	
	/* Toss any extra text currently displayed (used to help explain unloaded plugin, etc.)
	 */
	var show_hide_extra = document.getElementById("map_show_hide_extra_ID");
	if (show_hide_extra) {
		show_hide_extra.parentNode.removeChild(show_hide_extra);
	}
	
	/* If the map is displayed, then we want to replace it with a new empty hidden div.
	 * Replace the control appearance and message as well to reflect the new state.
	 */
	if (map_area.style.display == "block") {
		update_peak_name_links(false); // target peak_detail.php
		replace_google_earth_div();
		map_area.style.display = "none";
		show_hide.innerHTML = SHOW_HIDE_HIDDEN_HTML;
		show_hide.href = show_hide.href.replace(new RegExp('(.*show_google_earth=)false'),
												'$1true');
		
	/* Otherwise the map is not displayed, so we want to show it.
	 * Make sure the Google Earth APIs are loaded and then call show_google_earth() to
	 * create a brand new Google Earth plugin instance with our KML inside.
	 * Also replace the control appearance and message to reflect the (temporary) state.
	 */
	} else {
		map_area.style.display = "block";
		show_hide.innerHTML = SHOW_HIDE_LOADING_HTML;
		google.load("earth", "1", {"other_params":"sensor=false", "callback":show_google_earth});
	}
} 

/* Create a brand new Google Earth plugin instance, and then (re)fetch/parse our KML into it.
 * Also replace the control appearance and message to reflect the shown state when "finished".
 */
function show_google_earth() {
	build_google_earth(	document.getElementById("google_earth_ID"),
						finished_showing_map,
						error_showing_map);
}

/* Callback (from build_google_earth or a thread it spawns) after the Google Earth APIs
 * are loaded, the plugin is installed, the plugin_instance is created and installed
 * in the google_earh <div>, and the peak list KML is fetched into it.
 *
 * Here we set up our global reference to plugin_instance, update the placemark icons
 * for any peaks the climber has summited, turn the peak name links into "fly to"
 * commands, update the show/hide appearance and href to match the "shown" state,
 * and remember that the Google Earth plugin apparently works in this browser.
 */
function finished_showing_map(plugin_instance) {
	var show_hide = document.getElementById("map_show_hide_ID");

	google_earth_plugin = plugin_instance;
	update_climbed_peaks();
	update_peak_name_links(true); // target Google Earth
	show_hide.innerHTML = SHOW_HIDE_SHOWN_HTML;
	show_hide.href = show_hide.href.replace(new RegExp('(.*show_google_earth=)true'),
											'$1false');
	save_success_cookie(true);
}

/* Callback (from build_google_earth or a thread it spawns) after an error occurs.
 * In this case, an alert has already been shown, so we just remember that the
 * Google Earth plugin apparently fails in this browser, toss whatever's in
 * the google_earth <div>, hide the map area, and set the show/hide control to
 * match the "failed (try again?)" state.
 */
function error_showing_map() {
	save_success_cookie(false);

	var map_area = document.getElementById("google_earth_area_ID");
	var show_hide = document.getElementById("map_show_hide_ID");

	replace_google_earth_div();
	map_area.style.display = "none";
	show_hide.innerHTML = SHOW_HIDE_ERROR_HTML;
}

/* Remove and replace the <div> tag completely and null out our global Google Earth
 * plugin instance reference in order to release all memory associated with this
 * (old) instance, as otherwise Google Earth will be confused when we try to rebuild
 * things if and when the user decides to show it again.
 */
function replace_google_earth_div() {
	var google_earth_element = document.getElementById("google_earth_ID");
	if (google_earth_element) {
		google_earth_element.parentNode.removeChild(google_earth_element);
	}
	google_earth_plugin = null;
	var map_area = document.getElementById("google_earth_area_ID");
	var new_div = document.createElement("div");
	map_area.appendChild(new_div);
	new_div.setAttribute('id', 'google_earth_ID');
	new_div.className = 'google_earth';
}

/* Loop over all of the Google Earth peak placemarks in the KML document,
 * replacing each placemark icon with the "checked" version of that icon
 * if the climber has summited this peak. We don't include these icons in
 * the KML itself, because not all climbers wish to publish their climbs.
 */
function update_climbed_peaks() {
	
	/* Our KML document is fetched into the last feature of our (global) plugin instance.
	 */
	var ge = google_earth_plugin;
	var KML_document = ge.getFeatures().getLastChild();
	
	/* Loop over all of our placemarks, which are features of KML document.
	 * Each placemark has an ID of the form "peak_UID_nnn" where "nnn" is the peak UID.
	 * If the climber has climbed this peak, then the DOM will have an element
	 * <td id='climbed_peak_UID_nnn'> (containing the checkmark icon), so we know
	 * to replace that placemark's icon with the "checked" version,
	 */
	var placemarks = KML_document.getFeatures().getChildNodes();
	for (var placemark_index = 0;
		 placemark_index < placemarks.getLength();
		 placemark_index++) {
		var placemark = placemarks.item(placemark_index);
		if	(	(placemark.getType() == 'KmlPlacemark')
			&&	(document.getElementById('climbed_' + placemark.getId()))) {
			if (placemark.getStyleUrl() == '#passing_peak_ID') {
				placemark.setStyleUrl('#climbed_passing_peak_ID');
			} else if (placemark.getStyleUrl() == '#marginal_failing_peak_ID') {
				placemark.setStyleUrl('#climbed_marginal_failing_peak_ID');
			} else if (placemark.getStyleUrl() == '#clearly_failing_peak_ID') {
				placemark.setStyleUrl('#climbed_clearly_failing_peak_ID');
			}
		}
	}
}

/* Install an onUnload handler that removes all of the onClick handlers from the peak names.
 * This prevents memory leaks caused by circular references between the DOM and JavaScript
 * closure in update_peak_name_links.
 */
var GE_plugin__chained_onUnload_handler = VRMC__onUnload_handler;
VRMC__onUnload_handler = function() {
	update_peak_name_links(false);
	if (GE_plugin__chained_onUnload_handler) {
		GE_plugin__chained_onUnload_handler();
	}
}
	
/* Make sure that the peak names in the list link to the appropriate place given show/hide
 * state of the Google Earth panel. If target_google_earth is true, install onClick handlers
 * that "fly to" each peak's placemark. Otherwise, remove the handlers so that the hrefs
 * will link to the each peak's detail page.
 *
 * WARNING! Each onClick handler relies on a closure, so they must all be removed onUnload
 * to avoid memory leaks (see our VRMC__onUnload_handler above).
 */
function update_peak_name_links(target_google_earth) {
	
	/* If we've never loaded the Google Earth plugin successfully, then we haven't installed
	 * any onClick handlers in the peak name links (and we're just getting called by the
	 * onUnload handler to clean them up), so we're outta here.
	 */
	if (!google_earth_plugin) {
		return;
	}
	
	/* Our KML document is fetched into the last feature of our (global) plugin instance.
	 */
	var ge = google_earth_plugin;
	var KML_document = ge.getFeatures().getLastChild();
	
	/* Loop over all of our placemarks, which are features of KML document.
	 * Update the peak list's peak name link that's marked with the same peak UID.
	 */
	var placemarks = KML_document.getFeatures().getChildNodes();
	for (var placemark_index = 0;
		 placemark_index < placemarks.getLength();
		 placemark_index++) {
		var placemark = placemarks.item(placemark_index);
		if (placemark.getType() == 'KmlPlacemark') {
			update_peak_name_link(placemark);
		}
	}
	
	/* Also update all of the peak name column heading tool tips to match.
	 */
	update_peak_name_tip(document.getElementById('click_peak_name_tip_ID'));
	for (var tip_index = 1;
		 update_peak_name_tip(document.getElementById(		'click_peak_name_tip_'
														+	tip_index
														+	'_ID'));
		 tip_index++) {
	}
	
	/* Put a "fly to" link or null into the peak name link for this placemark.
	 */
	function update_peak_name_link(placemark) {
//		var peak_UID = placemark.getId().replace(new RegExp('peak_UID_(.*)'), '$1');
		var detail_link = document.getElementById(placemark.getId());
		if (detail_link) {
			detail_link.onclick
				=	(target_google_earth ?
						function() {
							var lookAt = ge.createLookAt('');
							var targetPoint = placemark.getGeometry();
							lookAt.setLatitude(targetPoint.getLatitude());
							lookAt.setLongitude(targetPoint.getLongitude());
							lookAt.set(	targetPoint.getLatitude(),
										targetPoint.getLongitude(),
										0, // height of target point (above ground)
										ge.ALTITUDE_RELATIVE_TO_GROUND,
										0, // eye heading (north)
										45, // tilt eye up toward north 45° from normal
										5000); // range (from eye to target point, 5 km)
							ge.getView().setAbstractView(lookAt);
							document.getElementById("google_earth_ID").scrollIntoView();
							return false;
						}
					:	null);
		}
	}
	
	/* Update the tip_element <span> (part of a peak name column heading tool tip)
	 * to match.
	 */
	function update_peak_name_tip(tip_element) {
		if (tip_element) {
			tip_element.innerHTML
				=	(target_google_earth ?
						(	"Click a peak name to &ldquo;fly to&rdquo; a location just above that summit"
						+	" in the Google Earth panel")
					:	"Click a peak name to see detailed peak information");
			return true;
		}
		return false;
	}
}